home *** CD-ROM | disk | FTP | other *** search
- /* skape <mmiller@hick.org */
-
- /*
- * dumps all the mapped memory segments in a running process
- */
- #include <stdlib.h>
- #include <stdio.h>
- #include <windows.h>
-
- #define PAGE_SIZE 4096
-
- typedef struct _MemoryRange
- {
-
- char *base;
- unsigned long length;
- char *file;
- struct _MemoryRange *next;
-
- } MemoryRange;
-
- BOOL createDumpDirectory(char *path);
- DWORD dumpSegments(HANDLE process, const char *dumpDirectory);
-
- int main(int argc, char **argv)
- {
- char *dumpDirectory = NULL;
- HANDLE process = NULL;
- DWORD pid = 0,
- segments = 0;
- int res = 1;
-
- do
- {
- // Validate arguments
- if ((argc == 1) ||
- (!(pid = atoi(argv[1]))))
- {
- printf("Usage: %s pid [dump directory]\n", argv[0]);
- break;
- }
-
- // If a dump directory is specified, use it, otherwise default
- // to the pid.
- if (argc >= 3)
- dumpDirectory = argv[2];
- else
- dumpDirectory = argv[1];
-
- // Create the dump directory (make sure it exists)
- printf("[*] Creating dump directory...%s\n", dumpDirectory);
-
- if (!createDumpDirectory(dumpDirectory))
- {
- printf("[-] Creation failed, %.8x.\n", GetLastError());
- break;
- }
-
- // Attach to the process
- printf("[*] Attaching to %lu...\n", pid);
-
- if (!(process = OpenProcess(PROCESS_VM_READ, FALSE, pid)))
- {
- printf("[-] Attach failed, %.8x.\n", GetLastError());
- break;
- }
-
- // Dump segments
- printf("[*] Dumping segments...\n");
-
- if (!(segments = dumpSegments(process, dumpDirectory)))
- {
- printf("[-] Dump failed, %.8x.\n", GetLastError());
- break;
- }
-
- printf("[*] Dump completed successfully, %lu segments.\n", segments);
-
- res = 0;
-
- } while (0);
-
- if (process)
- CloseHandle(process);
-
- return res;
- }
-
- /*
- * Create the directory specified by path, insuring that
- * all parents exist along the way.
- *
- * Just like MakeSureDirectoryPathExists, but portable.
- */
- BOOL createDumpDirectory(char *path)
- {
- char *slash = path;
- BOOL res = TRUE;
-
- do
- {
- slash = strchr(slash, '\\');
-
- if (slash)
- *slash = 0;
-
- if (!CreateDirectory(path, NULL))
- {
- if ((GetLastError() != ERROR_FILE_EXISTS) &&
- (GetLastError() != ERROR_ALREADY_EXISTS))
- {
- res = FALSE;
- break;
- }
- }
-
- if (slash)
- *slash++ = '\\';
-
- } while (slash);
-
- return res;
- }
-
- /*
- * Dump all mapped segments into the dump directory, one file per
- * each segment. Finally, create an index of all segments.
- */
- DWORD dumpSegments(HANDLE process, const char *dumpDirectory)
- {
- MemoryRange *ranges = NULL,
- *prevRange = NULL,
- *currentRange = NULL;
- char pbuf[PAGE_SIZE],
- rangeFileName[256];
- DWORD segments = 0,
- bytesRead = 0,
- cycles = 0;
- char *current = NULL;
- FILE *rangeFd = NULL;
-
- // Enumerate page by page
- for (current = 0;
- ;
- current += PAGE_SIZE, cycles++)
-
- {
- // If we've wrapped, break out.
- if (!current && cycles)
- break;
-
- // Invalid page? Cool, reset current range.
- if (!ReadProcessMemory(process, current, pbuf,
- sizeof(pbuf), &bytesRead))
- {
- if (currentRange)
- {
- prevRange = currentRange;
- currentRange = NULL;
- }
-
- if (rangeFd)
- {
- fclose(rangeFd);
-
- rangeFd = NULL;
- }
-
- continue;
- }
-
- // If the current range is not valid, we've hit a new range.
- if (!currentRange)
- {
- // Try to allocate storage for it, if we fail, bust out.
- if (!(currentRange = (MemoryRange *)malloc(sizeof(MemoryRange))))
- {
- printf("[-] Allocation failure\n");
-
- segments = 0;
-
- break;
- }
-
- currentRange->base = current;
- currentRange->length = 0;
- currentRange->next = NULL;
-
- if (prevRange)
- prevRange->next = currentRange;
- else
- ranges = currentRange;
-
- // Finally, open a file for this range
- _snprintf(rangeFileName, sizeof(rangeFileName) - 1, "%s\\%.8x.rng",
- dumpDirectory, current);
-
- if (!(rangeFd = fopen(rangeFileName, "wb")))
- {
- printf("[-] Could not open range file: %s\n", rangeFileName);
-
- segments = 0;
-
- break;
- }
-
- // Duplicate the file name for ease of access later
- currentRange->file = strdup(rangeFileName);
-
- // Increment the number of total segments
- segments++;
- }
-
- // Write to the range file
- fwrite(pbuf, 1, bytesRead, rangeFd);
-
- currentRange->length += bytesRead;
- }
-
- // Now that all the ranges are mapped, dump them to an index file
- _snprintf(rangeFileName, sizeof(rangeFileName) - 1, "%s\\index.rng",
- dumpDirectory);
-
- if ((rangeFd = fopen(rangeFileName, "w")))
- {
- char cwd[MAX_PATH];
-
- GetCurrentDirectory(sizeof(cwd), cwd);
-
- // Enumerate all of the ranges, dumping them into the index file
- for (currentRange = ranges;
- currentRange;
- currentRange = currentRange->next)
- {
- fprintf(rangeFd, "%.8x;%lu;%s\\%s\n",
- currentRange->base, currentRange->length, cwd,
- currentRange->file ? currentRange->file : "");
- }
-
- fclose(rangeFd);
- }
- else
- segments = 0;
-
- return segments;
- }
-